'''
    Goblinoid: Experience all of MediaGoblin on an Android Device
    Copyright (C) 2015 Dylan Jeffers

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
'''

from __future__ import print_function

from kivy.app import App
from kivy.lang import Builder
from kivy.clock import Clock, mainthread
from kivy.uix.screenmanager import Screen
from kivy.properties import ListProperty, BooleanProperty, NumericProperty,\
    ObjectProperty
from kivy.metrics import sp
# from kivy.garden.recycleview import RecycleView
from extensions.garden.recycleview import RecycleView
from functools import partial

from goblinoid.feed.refreshscrolleffect import RefreshScrollEffect
from goblinoid.libs.toast import toast

Builder.load_file('goblinoid/feed/kv/feedview.kv')


class RecycleFeed(RecycleView):

    refreshing_feed = BooleanProperty(False)
    new_data = ListProperty([])
    wait = NumericProperty(1)
    view = ObjectProperty()
    old_height = NumericProperty(0)
    container_height = NumericProperty()

    def __init__(self, **kwargs):
        super(RecycleFeed, self).__init__(**kwargs)
        self._container.bind(height=self.update_container_height)
        self.request_feed_refresh()
        self.data.append(dict([
            ('viewclass', 'Label')]))

    def on_pre_enter(self):
        if len(self.data) == 0 and not self.refreshing_feed:
            self.request_feed_refresh()

    def update_container_height(self, instance, height):
        self.container_height = height

    def on_container_height(self, instance, height):
        if height != 0:
            self.scroll_y = 1 - self.old_height / height
        else:
            self.scroll_y = 1
        # for debugging
        # print ('updated scroll_y: {0}'.format(self.scroll_y))
        # print ('height before and after: {0}, {1}'.format(self.old_height, height * (1 - self.scroll_y)))

    # NOTE: this toast sometimes force ends the app...
    @mainthread
    def request_feed_refresh(self):
        print ('feed refresh requested')
        app_will_refresh = App.get_running_app().pump_service.start_refresh(self.refresh_feed_with_new_data)
        if app_will_refresh:
            print ('refresh_feed called')
            self.refreshing_feed = True

    def on_data(self, instance, data):
        self.old_height = (1 - self.scroll_y) * self._container.height

    def on_scroll_y(self, instance, pos):
        if len(self.data) != 0:
            if pos < 1/(float((len(self.data)) ** (1.0/3))):
                App.get_running_app().pump_service.start_prefetch(self.append_prefetched_data)

    def on_refreshing_feed(self, instance, refreshing):
        if refreshing:
            App.get_running_app().dispatch_event("on_feed_refreshing")
            self.disabled = True
        else:
            self.disabled = False

    def refresh_feed_with_new_data(self, data_list):
        if len(data_list) > 0:
            self.refresh_feed(data_list)
            App.get_running_app().dispatch_event("on_feed_refreshed")
        # Clock.schedule_once(partial(self.refresh_feed, data_list))
        self.refreshing_feed = False

    def refresh_feed(self, data_list, *args):
        while len(self.data) > 0:
            self.data.pop()
        for data_item in data_list:
            self.data.append(data_item)

    def append_prefetched_data(self, data_list):
        # consider doing an extend here too
        for data_item in data_list:
            self.data.append(data_item)

    def on_disabled(self, instance, value):
        # doing this to keep from disabling the children, which was leading to problems
        pass

    def on_comment(self, *largs):
        try:
            index = largs[0]
            comment_obj = largs[1]
        except:
            return True
        data_index = 0
        for item in self.data:
            if item['viewclass'] == 'ViewCommentsButton' and item['index'] == index:
                text = unicode(comment_obj.content)
                item['count'] += 1
                # implies author is user. Somewhat hacky way, will come up with a
                # better implementation later
                # TODO DRY
                if comment_obj.author is None:
                    author = unicode(App.get_running_app().pump_service.pump.me.username)
                else:
                    author = unicode(comment_obj.author.username)
                formatted_comment = unicode('[ref=actor][color=86D4B1]{0}[/color][/ref] {1}'.format(author, text))
                self.data.insert(data_index+1, dict([
                    ("viewclass", "CommentSnapshot"),
                    ("author", author),
                    ("text", formatted_comment),
                    ("height", sp(20)),
                    ("index", index),
                    ("markup", True)]))
                break
            data_index += 1


class FeedView(Screen):
    data = ListProperty()

    def __init__(self, **kwargs):
        super(FeedView, self).__init__(**kwargs)
        self.register_event_type('on_comment')
        self._pump_service = App.get_running_app().pump_service
        self.ids.rv.effect_cls = RefreshScrollEffect

    def on_data(self, instance, value):
        print ('coming through to feedview')

    def on_comment(self, *largs):
        self.ids.rv.on_comment(*largs)
        return True

    def refresh_requested(self):
        print ('refresh requested')
